﻿using System;
using UnityEngine;
using UnityEngine.EventSystems;

namespace ZyGame
{
    public sealed class TouchObject : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
    {
        public enum TouchState
        {
            None,
            TouchStart,
            Touching,
            TouchEnded,
        }

        private Vector3 orgins;
        private float range = 100;
        private Rect rect = Rect.zero;
        private RectTransform rectTransform;
        private Action<TouchObject> callback;

        public Vector3 offset { get; private set; }

        public TouchState state { get; private set; }

        private void Awake()
        {
            orgins = this.transform.localPosition;
            rectTransform = this.transform.parent.GetComponent<RectTransform>();
        }

        public void SetTouchRange(Rect range)
        {
            rect = range;
        }

        public void SetTouchRange(float range)
        {
            this.range = range;
        }

        public void ListenerTouchEvent(Action<TouchObject> action)
        {
            callback = action;
        }

        private void FixedUpdate()
        {
            if (state == TouchState.Touching)
            {
                callback?.Invoke(this);
            }
        }

        public void OnDrag(PointerEventData eventData)
        {
            if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out Vector2 globalMousePos))
            {
                this.transform.localPosition = DragRangeLimit(globalMousePos);
                state = TouchState.Touching;
                offset = (this.transform.localPosition - orgins).normalized;
            }
        }

        public void OnEndDrag(PointerEventData eventData)
        {
            state = TouchState.TouchEnded;
            offset = Vector3.zero;
            this.transform.localPosition = orgins;
            callback?.Invoke(this);
        }

        public void OnBeginDrag(PointerEventData eventData)
        {
            state = TouchState.TouchStart;
            callback?.Invoke(this);
        }

        // 限制坐标范围
        Vector3 DragRangeLimit(Vector3 pos)
        {
            if (rect == Rect.zero)
            {
                float distrance = Vector3.Distance(pos, orgins);
                if (distrance > range)
                {
                    return (pos - orgins).normalized * range;
                }

                return pos;
            }

            pos.x = Mathf.Clamp(pos.x, orgins.x - rect.width / 2, orgins.x + rect.width / 2);
            pos.y = Mathf.Clamp(pos.y, orgins.y - rect.height / 2, orgins.y + rect.height / 2);
            return pos;
        }
    }
}